package com.arpgalaxy.generator.core;

import com.arpgalaxy.generator.entity.*;
import com.arpgalaxy.generator.utils.BeanUtils;
import com.arpgalaxy.generator.utils.DataBaseUtils;
import com.arpgalaxy.generator.utils.FileUtils;
import com.arpgalaxy.generator.utils.FreemarkerUtils;
import freemarker.template.Configuration;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author arpgalaxy
 * @date 2021/4/5
 * @email 13605560342@163.com
 * @description
 */

public class ArpGenerator {

    /**
     * 获取数据模型
     */


    /**
     * 执行生成器
     *  1.获取freemarker 配置类
     *  2.数据处理
     *  3.循环扫描并生成模板文件
     */
    public  void executeGenerator(Properties properties, TypeConverter typeConverter){
        //1.
        Configuration configuration = FreemarkerUtils.getConfiguration();
        //2.
//        properties.setModule(StringUtils.firstToUpperCase(properties.getModule()));
        //3.
        List<DataBase> dbs = DataBaseUtils.getDataBaseList(properties);
        for (DataBase dataBase : dbs) {
            System.out.println(dataBase+" 正在生成...");
            try {
                List<Table> dbInfo = DataBaseUtils.getDbInfo(dataBase, typeConverter,dataBase.getDbName(),properties);
                Map<String, String> dataModel = new HashMap<>();
                dataModel.put("dbName",dataBase.getDbName());
                if (dbInfo != null && dbInfo.size() != 0)
                    dbInfo.stream().forEach((table) -> {
                        System.out.println("Table 配置: "+table.getName());
                        properties.setTable(table);
                        scanAndGenerate(configuration, properties,dataModel);
                    });
                else scanAndGenerate(configuration, properties,dataModel);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(dataBase+" 生成完成！");
        }
    }


    public void scanAndGenerate(Configuration configuration, Properties properties, Map<String,String> dataModel){
        Path template = Paths.get(properties.getTemplate());
        Path target= Paths.get(properties.getTarget());
        Map<String, String> beanMap = BeanUtils.beanToHashMap(properties);
        beanMap.putAll(dataModel);
        Stream<Path> walk = null;
        try {
            walk = Files.walk(template);
        } catch (IOException e) {
            e.printStackTrace();
        }
        walk.filter((f)->{
            if (f.getFileName().equals(template.getFileName()))return false;
            return true;
        }).forEach((f)->{
            System.out.println("f-filename:"+f);try {
                if (Files.isDirectory(f)){

                    String dirName = FreemarkerUtils.executePathGenerator(configuration, beanMap, f);
                    dirName = dirName.toLowerCase();
                    Path path = FileUtils.tempPathToTarget(dirName, properties);
                    if (!Files.exists(path))
                        Files.createDirectories(path);
                }else if (
                        endWithStrings(f.toString(),
                        new String[]{"Application.java","application.yml","pom.xml"})
                        ||
                        properties.getTable()!=null
                ){
                    boolean b = FreemarkerUtils.executeFileGenerator(configuration,properties, beanMap, f);
                    System.out.println("生成文件:" + f.getFileName());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("f-parent:"+f.getParent());
        });
    }
    public boolean endWithStrings(String string,String [] endStrings){
        List<String> residue = Arrays.stream(endStrings).filter((s) -> {
            return string.endsWith(s);
        }).collect(Collectors.toList());
        return residue.size()==0?false:true;
    }
}